#pragma once
#include <iostream>
#include <algorithm>
#include <poll.h>
#include <sys/time.h>
#include "Socket.hpp"
#include "Log.hpp"
using std::cout;
using std::endl;
const static int default_port = 8888;
const static int max_size = 1024;
const static int default_val = -1;
const static int default_null = 0;
class PollServer
{
public:
    PollServer(int port = default_port)
        : _port(port)
    {
    }
    ~PollServer()
    {
        _listenSock.Close();
    }
    void Init()
    {
        _listenSock.Socket();
        _listenSock.Bind(_port);
        _listenSock.Listen();
        for (size_t i = 0; i < max_size; i++)
        {
            _fds[i].fd = default_val;
            _fds[i].events = default_null;
            _fds[i].revents = default_null;
        }
    }

    void PrintFd()
    {
        cout << "rfds: ";
        for (size_t i = 0; i < max_size; i++)
        {
            if (_fds[i].fd != default_val)
            {
                cout << _fds[i].fd << " ";
            }
            cout << endl;
        }
    }
    void Start()
    {
        int listenSock = _listenSock.Fd();
        _fds[0].fd = listenSock;
        _fds[0].events = POLLIN; //care for read
        _fds[0].revents = default_null; //care for read
        int timeout = -1;
        
        while (1)
        {

            int n = poll(_fds, max_size, timeout);
            switch (n)
            {
            case 0:
                cout << "time out" << endl;
                break;
            case -1:
                break;
            default:
                Dispatcher();
                break;
            }
        }
    }
    void Dispatcher()
    {
        for (size_t i = 0; i < max_size; i++)
        {
            if(_fds[i].fd != default_val)
            {
                if(_fds[i].revents & POLLIN)
                {
                    if(_fds[i].fd == _listenSock.Fd())
                    {
                        Accepter(); //链接管理器
                    }
                    else
                    {
                        Recver(_fds[i].fd, i);
                    }
                }
            }
        }
    }

    void Accepter()
    {
        std::string clientIp;
        uint16_t clientPort;
        int sock = _listenSock.Accept(&clientIp, &clientPort);
        lg(Info, "Accept a new sock: %d, clientip: %s, clientport: %d", sock, clientIp.c_str(), clientPort);
        size_t i = 0;
        for (; i < max_size; i++)
        {
            if (_fds[i].fd == default_val)
            {
                _fds[i].fd = sock;
                _fds[i].events = POLLIN;
                break;
            }
        }
        if (i == max_size)
        {
            // to do...
            lg(Warning, "server is full");
            close(sock);
        }
    }
    void Recver(int sock, int pos)
    {
        char buffer[1024];
        ssize_t n = read(sock, buffer, sizeof(buffer) - 1);
        if (n > 0)
        {
            buffer[n] = 0;
            cout << "echo# " << buffer << endl;
        }
        else if (n == 0)
        {
            printf("client quit, i will close sock: %d\n", sock);
            _fds[pos].fd = default_val;
            _fds[pos].events = default_null;
            _fds[pos].revents = default_null;
            close(sock);
            return;
        }
        else
        {
            cout << "read ,i will close sock" << endl;
            _fds[pos].fd = default_val;
            _fds[pos].events = default_null;
            _fds[pos].revents = default_null;
            close(sock);
            return;
        }
    }

private:
    Sock _listenSock;
    uint16_t _port;
    struct pollfd _fds[max_size];
};